package com.nescafe.nescafepromo.command.admin;

import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.SortDirection;
import com.google.appengine.api.datastore.QueryResultList;
import com.nescafe.nescafepromo.command.Command;
import com.nescafe.nescafepromo.command.CommandException;
import com.nescafe.nescafepromo.entity.EntityType;
import com.nescafe.nescafepromo.entity.Participant;
import com.nescafe.nescafepromo.entity.TotalPoints;
import com.nescafe.nescafepromo.model.NPRequest;
import com.nescafe.nescafepromo.model.NPResponse;
import com.nescafe.nescafepromo.model.ParticipantDetailList;

public class SearchParticipants implements Command {

	@Override
	public NPResponse execute(NPRequest req) throws CommandException {
		NPResponse res = null;
		try {
			ParticipantDetailList pdList = new ParticipantDetailList();
			res = new NPResponse(pdList);
			String email = req.getParam("email");
			DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
			if (email != null && !email.isEmpty()) {
				Key participantKey = EntityType.PARTICIPANT.getKey(email);
				try {
					Entity participantEntity = ds.get(participantKey);
					Key totalPointsKey = EntityType.TOTAL_POINTS.getKey(participantKey, email);
					Entity tPointsEntity = ds.get(totalPointsKey);
					Participant participant = new Participant(participantEntity);
					participant.setTotalPoints(new TotalPoints(tPointsEntity));
					pdList.addParticiPant(participant);

				} catch (EntityNotFoundException e) {

				}
			} else {
				int pageSize = 15;
				String cursor = req.getParam("cursor");
				FetchOptions fetchOptions = FetchOptions.Builder.withLimit(pageSize);
				if (cursor != null) {
					fetchOptions.startCursor(Cursor.fromWebSafeString(cursor));
				}

				Query q = new Query(EntityType.TOTAL_POINTS.getKind());
				q.addSort(TotalPoints.TOTAL_POINTS_FIELD, SortDirection.DESCENDING);
				PreparedQuery pq = ds.prepare(q);
				QueryResultList<Entity> pointsResult = pq.asQueryResultList(fetchOptions);
				res.setCursor(pointsResult.getCursor());

				q = new Query(EntityType.PARTICIPANT.getKind());
				List<Key> participantKeys = new ArrayList<Key>();
				for (Entity tpEntity : pointsResult) {
					Key pKey = EntityType.PARTICIPANT.getKey(tpEntity.getKey().getName());
					participantKeys.add(pKey);
				}
				q.addFilter(Entity.KEY_RESERVED_PROPERTY, FilterOperator.IN, participantKeys);
				pq = ds.prepare(q);
				List<Entity> participantsResult = pq.asList(FetchOptions.Builder.withLimit(pageSize));

				for (Entity e : participantsResult) {
					pdList.addParticiPant(new Participant(e));
				}
				for (Entity tpEntity : pointsResult) {
					pdList.addTotalPoints(new TotalPoints(tpEntity));
				}
			}
		} catch (Exception e) {
			throw new CommandException(e.getMessage());
		}
		return res;
	}
}
